using System;
using System.Linq;
using System.Collections.Generic;

namespace BSDS.Core.Model.Data
{
    public class EntityValue
    {
        public string PrimaryKeyValue
        {
            get { return AttributeValues.First(av => av.AttributeInfo.IsPrimaryKey).Value; }
        }

        public List<AttributeInfo> AttributeInfos
        {
            get { return AttributeValues.Select(av => av.AttributeInfo).ToList(); }
        }

        public List<AttributeValue> AttributeValues { get; private set; }

        public EntityValue(List<AttributeValue> attributeValues)
        {
            AttributeValues = attributeValues;
        }

        public string GetAttributeValue(string name)
        {
            if(AttributeValues.Any(av => av.AttributeInfo.Name == name))
            {
                return AttributeValues.First(av => av.AttributeInfo.Name.Equals(name, StringComparison.CurrentCultureIgnoreCase)).Value;
            }
            
            return string.Empty;
        }

        public void UpdateAttributeFromOtherEntity(EntityValue otherEntity, string attributeName)
        {
            var otherAttribute = otherEntity.AttributeValues.FirstOrDefault(a => a.AttributeInfo.Name == attributeName);
            
            if (otherAttribute != null)
            {
                UpdateAttributeValue(attributeName, otherAttribute.Value);
            }
        }

        public void UpdateAttributeValue(string attributeName, string attributeValue)
        {
            var attribute = AttributeValues.FirstOrDefault(a => a.AttributeInfo.Name == attributeName);

            if (attribute != null)
            {
                attribute.Value = attributeValue;
            }
        }

        public void RemoveAttributeValue(string attributeName)
        {
            AttributeValues.Remove(AttributeValues.FirstOrDefault(x => x.AttributeInfo.Name == attributeName));
        }

        public void InsertAttributeValue(AttributeValue value, string before)
        {
            int index = AttributeValues.IndexOf(AttributeValues.FirstOrDefault(x => x.AttributeInfo.Name == before));

            if (index >= 0)
            {
                AttributeValues.Insert(index, value);
            }
        }

        public void AppendAttributeValue(AttributeValue value)
        {
            AttributeValues.Add(value);
        }

        public void RenameAttribute(string oldName, string newName)
        {
            AttributeInfos.FirstOrDefault(x => x.Name == oldName).Name = newName;
        }

        public override string ToString()
        {
            return AttributeValues.First(a => a.AttributeInfo.IsPrimaryKey).Value;
        }

        public bool HasValidCoordinates()
        {
            var latitude = GetAttributeValue("Latitude");   
            var longitude = GetAttributeValue("Longitude"); 

            return !string.IsNullOrEmpty(latitude) && !string.IsNullOrEmpty(longitude);
        }

        public bool HasValidNonZeroCoordinates()
        {
            double latitude, longitude;

            if (double.TryParse(GetAttributeValue("Latitude"), out latitude) && double.TryParse(GetAttributeValue("Longitude"), out longitude))
            {
                return latitude != 0.0 || longitude != 0.0;
            }

            return false;
        }

        public bool IsFailedEntity()
        {
            return GetAttributeValue("StatusCode") == "Failed";
        }

        public bool IsHighConfidence()
        {
            return GetAttributeValue("Confidence") == "High";
        }

        public bool IsImpreciseEntity()
        {
            var confidence = GetAttributeValue("Confidence");
            return confidence == "Medium" || confidence == "Low";
        }

        public bool IsImpreciseOrBadEntity()
        {
            var confidence = GetAttributeValue("Confidence");
            return confidence == "Medium" || confidence == "Low" || confidence == "BadRequest";
        }

        public bool HasObligatoryColumns()
        {
            return AttributeInfos.Any(ai => ai.Name == "Latitude") && AttributeInfos.Any(ai => ai.Name == "Longitude");
        }

        public bool HasPrimaryKeyDefined()
        {
            return AttributeValues.Any(a => a.AttributeInfo.IsPrimaryKey);
        }
    }
}
